package com.hhf.riceshopping.search.thread;

import java.util.concurrent.*;

public class ThreadTest {
    public  static ExecutorService executor = Executors.newFixedThreadPool(10);//一个固定数量的线程池

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start....");
//        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运行结果: " + i);
//        }, executor);
//            CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 0;
//            System.out.println("运行结果: " + i);
//            return i;
//        }, executor).whenComplete((res,excption)->{
//                System.out.println("异步任务成功完成了...结果是："+res+";异常是："+excption);
//            }).exceptionally(throwable ->{
//                return 10;
//            });
//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 4;
//            System.out.println("运行结果: " + i);
//            return i;
//        }, executor).handle((res,thr)->{
//            if (res!=null){
//                return res*2;
//            }
//            if (thr!=null){
//                return 0;
//            }
//            return 0;
//        });

        /**
         * 线程串行话化
         * thenRunAsync:不能获取倒上一步的执行结果
         * .thenRunAsync(() -> {
         *             System.out.println("任务2启动.. ");
         *         }, executor);
         *
         * thenAcceptAsync:能接收倒上一步运行后的结果进行进一步的处理，但是无返回值
         * .thenAcceptAsync(res->{
         *              System.out.println("任务2启动.. "+res);
         *          },executor);
         *
         * thenApplyAsync:既能获取倒上一步的运行结果并进行进一步的处理，还能有返回值，
         * 然后可以再吧这个返回值交给另外一个运行的异步任务进行再进一步的处理
         */
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("运行结果: " + i);
            return i;
        }, executor).thenApplyAsync(res -> {
            System.out.println("任务2启动.. " + res);
            return "hello " + res;
        }, executor);

//        Integer integer = future1.get();
        System.out.println("main....end...."+future.get());
//        System.out.println("main....end....");

    }


    public  void thread(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start....");
        /**
         *
         * 1）、继承 Thread  不能得到返回值
         *   Thread01 thread = new Thread01();
         *         thread.start();//启动线程
         *         System.out.println("main....end....");
         *
         * 2）、实现 Runnable 接口 不能得到返回值
         * Runable01 runable01 = new Runable01();
         *         new Thread(runable01).start();
         *
         * 3）、实现 Callable 接口 + FutureTask （可以拿到返回结果，可以处理异常）
         *   //阻塞等待整个线程执行完成，获取返回结果
         *         FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
         *         new Thread(futureTask).start();
         *         Integer integer = futureTask.get();
         * 4）、线程池
         * service.execute(new Runable01());
         */

        /**
         *  七大参数
         *  corePoolSize:核心线程数
         *  maximumPoolSize:最大线程数
         *  keepAliveTime：存活时间，如果当前的线程数量大于核心数量。只要线程空闲大于指定的存活时间就会释放空闲的最大线程数的线程
         *  unit：  时间单位
         *  BlockingQueue<Runnable> workQueue：阻塞队列，如果任务多，就会将目前多的任务放在队列里面
         *                                      只要有线程空闲，就会去队列里面取出新的任务继续执行
         *  ThreadFactory ：线程的创建工厂
         *  RejectedExecutionHandler：拒绝策略，也就是用于阻塞队列满了怎么办的一个参数
         *
         *  工作流程：
         *      1、线程池创建，准备好 core 数量的核心线程，准备接受任务
         *      2、core 满了，就将再进来的任务放入阻塞队列中。空闲的 core 就会自己去阻塞队列获取任务执行
         *      3、阻塞队列满了，就直接开新线程执行，最大只能开到 max 指定的数量
         *      4、max 都执行好了。Max-core 数量空闲的线程会在 keepAliveTime 指定的时间后自动销毁。最终保持到 core 大小
         *      5、如果线程数开到了 max 的数量，还有新任务进来，就会使用 指定的拒绝策略进行处理
         *      6、所有的线程创建都是由指定的 factory 创建的。
         */
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,
                200,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardPolicy());  //把最新过来的丢弃，并且不抛出异常


        System.out.println("main....end....");

    }

    public static class Thread01 extends Thread{
        @Override
        public void run() {
            System.out.println("当前线程："+Thread.currentThread().getId());
            int i =10/2;
            System.out.println("运行结果: "+i);
        }


    }

    public static class Runable01 implements  Runnable{

        @Override
        public void run() {
            System.out.println("当前线程："+Thread.currentThread().getId());
            int i =10/2;
            System.out.println("运行结果: "+i);
        }
    }

    public static class Callable01 implements Callable<Integer>{

        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程："+Thread.currentThread().getId());
            int i =10/2;
            System.out.println("运行结果: "+i);
            return i;
        }
    }
}
